package com.miaocat19.controller;

import com.miaocat19.controller.viewobject.UserVO;
import com.miaocat19.error.BusinessException;
import com.miaocat19.error.EmBusinessError;
import com.miaocat19.response.CommonReturnType;
import com.miaocat19.service.UserService;
import com.miaocat19.service.model.UserModel;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import com.alibaba.druid.util.StringUtils;
import sun.misc.BASE64Encoder;

import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Random;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @program: Javamiaosha
 * @description:
 * @author: miaocat19
 * @create: 2021-12-08 17:21
 **/

/*
 *   这个处理器总过有四个接口
 *
 *   1、第一个方法   getUserById
 *   getUserById  目前我忘记是做什么用的方法了
 *   注意点：
 *   在这个方法中
 *   （1）、就是要注意下 service中的对象向controller层中的对象转化的过程
 *   使用了spring中的BeanUtils中的对象copy方法
 *   BeanUtils.copyProperties(userModel, userVO);
 *
 *   （2）
 *   方法在返回时 我们做了封装
 *   创建了CommonReturnType对象 来封装对象
 *   作用写在了这个对象的里面
 *
 *   2、第二个方法   getOtp
 *   获取验证码   这个方法是我们在注册用户之前 我们需要获取一下验证码
 *
 *   使用Random函数生成值
 *   httpServletRequest.getSession().setAttribute(telphone, otpCode);
 *
 *
 *  3、第三个接口
 *  register注册接口
 *
 *  httpServletRequest.getSession().getAttribute(telphone);
 *  在这地方我们进行获取验证码   这个验证码 和 用户输入的验证码进行比比较  比较是不是相等
 *  然后进行注册
 *  这个地方我们在下面的地方已经分析过了
 *
 *  4、登录接口
 *  我们这个地方登录使用了token进行了实现
 *  这个我们把token放入了redis进行存储
 *  这个地方我们不适用session  因为我们要开多台服务器
 *  如果放在服务器就会不知道放在哪个服务器造成
 *  这个token
 *  还有一个事情我们把生成的token同时传给前端
 *  前端使用windows.localStorage 放到这个地方  这个我们会在下单的时候进行校验
 *
 *  这个地方我么说一下 我们进行怎么样的校验呢 我们首先像前端拿一下
 *  这个值String token = httpServletRequest.getParameterMap().get("token")[0];
 *
 *  这个关于怎么向redis传值
 *  redisTemplate.opsForValue().set(uuidToken, userModel);
 *
 *  设置过期时间
 *  redisTemplate.expire
 *
 * */




@Controller("user")
@RequestMapping("/user")
@CrossOrigin(allowCredentials = "true", allowedHeaders = "*")
public class UserContoller extends BaseContoller {

    @Autowired
    private UserService userService;

    @Autowired
    private HttpServletRequest httpServletRequest;

    @Autowired
    private RedisTemplate redisTemplate;


    @RequestMapping("/get")
    @ResponseBody
    public CommonReturnType getUser(@RequestParam(name = "id") Integer id) throws BusinessException {
        //调用service对象并返回给前端
        UserModel userById = userService.getUserById(id);

        if (userById == null) {
            throw new BusinessException(EmBusinessError.USER_NOT_EXIST);
        }

        UserVO userVO = covertFromUserModel(userById);

        return CommonReturnType.create(userVO);
    }


    /*获取验证码*/
    @RequestMapping(value = "getotp", method = {RequestMethod.POST}, consumes = {CONTENT_TYPE_FORMED})
    @ResponseBody
    public CommonReturnType getOtp(@RequestParam(name = "telphone") String telphone) {
        /*使用random函数创建  对象  实现自己生成验证码*/
        Random random = new Random();
        int randomInt = random.nextInt(99999);
        randomInt += 10000;
        String otpCode = String.valueOf(randomInt);

        //将OTP验证码同对应用户的手机号关联，使用httpsession的方式绑定他的手机号与OTPCODE
        httpServletRequest.getSession().setAttribute(telphone, otpCode);

        System.out.println("telphone-----" + telphone + " & otpCode = " + otpCode);

        return CommonReturnType.create(null);
    }


    //用户注册接口
    @RequestMapping(value = "/register", method = {RequestMethod.POST}, consumes = {CONTENT_TYPE_FORMED})
    @ResponseBody
    public CommonReturnType register(@RequestParam(name = "telphone") String telphone,
                                     @RequestParam(name = "otpCode") String otpCode,
                                     @RequestParam(name = "name") String name,
                                     @RequestParam(name = "gender") Integer gender,
                                     @RequestParam(name = "age") Integer age,
                                     @RequestParam(name = "password") String password) throws BusinessException, UnsupportedEncodingException, NoSuchAlgorithmException {

        //验证手机号和对应的otpcode相符合
        String inSessionOtpCode = (String) this.httpServletRequest.getSession().getAttribute(telphone);

        System.out.println("inSessionOtpCode-----" + inSessionOtpCode);

        /*我们这个地方判断方式是使用了 StrigUtils的方式*/
        if (!com.alibaba.druid.util.StringUtils.equals(otpCode, inSessionOtpCode)) {
            throw new BusinessException(EmBusinessError.PARAMETER_VALIDATION_ERROR, "短信验证码不符合");
        }
        /*创建一个userModel对象
         * 然后生成对象
         * */
        //用户的注册流程
        UserModel userModel = new UserModel();
        userModel.setName(name);
        userModel.setGender(new Byte(String.valueOf(gender.intValue())));
        userModel.setAge(age);
        userModel.setTelphone(telphone);
        userModel.setRegisterMode("byphone");
        userModel.setEncrptPassword(this.EncodeByMd5(password));

        /*调用service接口
         * 进行注册
         * */
        /*注册*/
        userService.register(userModel);


        return CommonReturnType.create(null);
    }


    /*用户的登录接口*/
    @RequestMapping(value = "login", method = {RequestMethod.POST}, consumes = {CONTENT_TYPE_FORMED})
    @ResponseBody
    public CommonReturnType login(@RequestParam(name = "telphone") String telphone,
                                  @RequestParam(name = "password") String password) throws UnsupportedEncodingException, NoSuchAlgorithmException, BusinessException {


        //入参校验
        if (StringUtils.isEmpty(telphone) || StringUtils.isEmpty(password)) {
            throw new BusinessException(EmBusinessError.PARAMETER_VALIDATION_ERROR);
        }

        //用户登陆服务,用来校验用户登陆是否合法
        UserModel userModel = userService.validateLogin(telphone, this.EncodeByMd5(password));

        /*使用uuid生成token*/
        String uuidToken = UUID.randomUUID().toString();

        uuidToken = uuidToken.replace("-", "");

        /*建立token和用户态之间的联系*/
        redisTemplate.opsForValue().set(uuidToken, userModel);

        /*设置过期时间*/
        redisTemplate.expire(uuidToken, 1, TimeUnit.HOURS);


        //将登陆凭证加入到用户登陆成功的session内
//        this.httpServletRequest.getSession().setAttribute("IS_LOGIN", true);
//        this.httpServletRequest.getSession().setAttribute("LOGIN_USER", userModel);
        /*返回token 这个是前端拿到的token，这个前端拿到之后 我们就可以   可以和数据库中做对比  然后进行登录*/
        return CommonReturnType.create(uuidToken);
    }


    /*生成md5的方法*/
    private String EncodeByMd5(String password) throws NoSuchAlgorithmException, UnsupportedEncodingException {
        /*确定加密方法*/
        MessageDigest md5 = MessageDigest.getInstance("MD5");

        BASE64Encoder base64en = new BASE64Encoder();
        /*添加加密字符串*/
        String encode = base64en.encode(md5.digest(password.getBytes("utf-8")));

        return encode;
    }


    /*对象的转换，通过service层的对象转换成vo层的对象*/
    private UserVO covertFromUserModel(UserModel userModel) {
        UserVO userVO = new UserVO();
        BeanUtils.copyProperties(userModel, userVO);
        return userVO;
    }


}
